1#!/usr/bin/perl
2
3use strict;
4use warnings;
5
6use Test::More 0.88;
7
8use Math::Int128 qw(uint128 uint128_to_number
9                    net_to_uint128 uint128_to_net
10                    native_to_uint128 uint128_to_native);
11
12my $i = uint128('1234567890123456789');
13my $j = $i + 1;
14my $k = (uint128(1) << 60) + 255;
15
16# 1
17ok($i == '1234567890123456789');
18
19ok($j - 1 == '1234567890123456789');
20
21ok (($k & 127) == 127);
22
23ok (($k & 256) == 0);
24
25# 5
26ok ($i * 2 == $j + $j - 2);
27
28ok ($i * $i * $i * $i == ($j * $j - 2 * $j + 1) * ($j * $j - 2 * $j + 1));
29
30ok (($i / $j) == 0);
31
32ok ($j / $i == 1);
33
34ok ($i % $j == $i);
35
36# 10
37ok ($j % $i == 1);
38
39ok (($j += 1) == $i + 2);
40
41ok ($j == $i + 2);
42
43ok (($j -= 3) == $i - 1);
44
45ok ($j == $i - 1);
46
47$j = $i;
48# 15
49ok (($j *= 2) == $i << 1);
50
51ok (($j >> 1) == $i);
52
53ok (($j / 2) == $i);
54
55$j = $i + 2;
56
57ok (($j %= $i) == 2);
58
59ok ($j == 2);
60
61# 20
62ok (($j <=> $i) < 0);
63
64ok (($i <=> $j) > 0);
65
66ok (($i <=> $i) == 0);
67
68ok (($j <=> 2) == 0);
69
70ok ($j < $i);
71
72# 25
73ok ($j <= $i);
74
75ok (!($i < $j));
76
77ok (!($i <= $j));
78
79ok ($i <= $i);
80
81ok ($j >= $j);
82
83# 30
84ok ($i > $j);
85
86ok ($i >= $j);
87
88ok (!($j > $i));
89
90ok (!($j >= $i));
91
92ok (int(log(uint128(1)<<50)/log(2)+0.001) == 50);
93
94# 35
95
96my $l = uint128("127131031961723452345");
97
98is ("$l", "127131031961723452345", "string to/from int128 conversion");
99
100ok (native_to_uint128(uint128_to_native(1)) == 1);
101
102ok (native_to_uint128(uint128_to_native(0)) == 0);
103
104ok (native_to_uint128(uint128_to_native(12343)) == 12343);
105
106ok (native_to_uint128(uint128_to_native($l)) == $l);
107
108# 40
109
110ok (native_to_uint128(uint128_to_native($j)) == $j);
111
112ok (native_to_uint128(uint128_to_native($i)) == $i);
113
114ok (net_to_uint128(uint128_to_net(1)) == 1);
115
116ok (net_to_uint128(uint128_to_net(0)) == 0);
117
118ok (net_to_uint128(uint128_to_net(12343)) == 12343);
119
120# 45
121
122ok (net_to_uint128(uint128_to_net($l)) == $l);
123
124ok (net_to_uint128(uint128_to_net($j)) == $j);
125
126ok (net_to_uint128(uint128_to_net($i)) == $i);
127
128{
129    use integer;
130    my $int = uint128(255);
131    ok($int == 255);
132    $int <<= 32;
133    $int |= 4294967295;
134    ok($int == '1099511627775');
135}
136
137my $two  = uint128(2);
138my $four = uint128(4);
139is ($two  ** -1, 0, "signed pow 2**-1");
140is ($four ** -1, 0, "signed pow 4**-1");
141
142sub slow_pow_uint128 {
143    my ($a, $b) = @_;
144    my $acu = uint128(1);
145    $acu *= $a for 1..$b;
146    $acu;
147}
148
149sub slow_pow_nv {
150    my ($base, $exp) = @_;
151    my $r = 1;
152    $r *= $base for 1..$exp;
153    $r
154}
155
156my $max = (((uint128(2) ** 127) - 1) * 2) + 1;
157for my $j (0..127) {
158    my $one = uint128(1);
159
160    is($two  ** $j, $one <<     $j, "signed pow 2**$j");
161    is($four ** $j, $one << 2 * $j, "signed pow 4**$j") if $j < 64;
162
163    is($one << $j, $two ** $j, "$one << $j");
164
165    $one <<= $j;
166    is($one, $two ** $j, "$one <<= $j");
167
168    next unless $j;
169
170    my $pow2j = slow_pow_nv(2, $j);
171
172    is($max >> $j, $max / $pow2j, "max uint128 >> $j");
173
174    my $copy = uint128($max);
175    $copy >>= $j;
176    is($copy, $max / $pow2j, "max uint128 >>= $j");
177}
178
179for my $i (5..9) {
180    for my $j (0..40) { # 9**40 < 2**127
181        is(uint128($i) ** $j, slow_pow_uint128($i, $j), "signed pow $i ** $j");
182    }
183}
184
185done_testing();
186