1#!perl
2
3use strict;
4use warnings;
5
6use Test::More tests => 379;
7
8use Math::BigInt::Calc;
9
10my ($BASE_LEN, undef, $AND_BITS, $XOR_BITS, $OR_BITS,
11    $BASE_LEN_SMALL, $MAX_VAL)
12  = Math::BigInt::Calc->_base_len();
13
14print "# BASE_LEN = $BASE_LEN\n";
15print "# MAX_VAL  = $MAX_VAL\n";
16print "# AND_BITS = $AND_BITS\n";
17print "# XOR_BITS = $XOR_BITS\n";
18print "# IOR_BITS = $OR_BITS\n";
19
20# testing of Math::BigInt::Calc
21
22my $LIB = 'Math::BigInt::Calc';         # pass classname to sub's
23
24# _new and _str
25
26my $x = $LIB->_new("123");
27my $y = $LIB->_new("321");
28is(ref($x), "Math::BigInt::Calc", q|ref($x) is an Math::BigInt::Calc|);
29is($LIB->_str($x), 123,     qq|$LIB->_str(\$x) = 123|);
30is($LIB->_str($y), 321,     qq|$LIB->_str(\$y) = 321|);
31
32###############################################################################
33# _add, _sub, _mul, _div
34
35is($LIB->_str($LIB->_add($x, $y)), 444,
36   qq|$LIB->_str($LIB->_add(\$x, \$y)) = 444|);
37is($LIB->_str($LIB->_sub($x, $y)), 123,
38   qq|$LIB->_str($LIB->_sub(\$x, \$y)) = 123|);
39is($LIB->_str($LIB->_mul($x, $y)), 39483,
40   qq|$LIB->_str($LIB->_mul(\$x, \$y)) = 39483|);
41is($LIB->_str($LIB->_div($x, $y)), 123,
42   qq|$LIB->_str($LIB->_div(\$x, \$y)) = 123|);
43
44###############################################################################
45# check that mul/div doesn't change $y
46# and returns the same reference, not something new
47
48is($LIB->_str($LIB->_mul($x, $y)), 39483,
49   qq|$LIB->_str($LIB->_mul(\$x, \$y)) = 39483|);
50is($LIB->_str($x), 39483,
51   qq|$LIB->_str(\$x) = 39483|);
52is($LIB->_str($y), 321,
53   qq|$LIB->_str(\$y) = 321|);
54
55is($LIB->_str($LIB->_div($x, $y)), 123,
56   qq|$LIB->_str($LIB->_div(\$x, \$y)) = 123|);
57is($LIB->_str($x), 123,
58   qq|$LIB->_str(\$x) = 123|);
59is($LIB->_str($y), 321,
60   qq|$LIB->_str(\$y) = 321|);
61
62$x = $LIB->_new("39483");
63my ($x1, $r1) = $LIB->_div($x, $y);
64is("$x1", "$x", q|"$x1" = "$x"|);
65$LIB->_inc($x1);
66is("$x1", "$x", q|"$x1" = "$x"|);
67is($LIB->_str($r1), "0", qq|$LIB->_str(\$r1) = "0"|);
68
69$x = $LIB->_new("39483");       # reset
70
71###############################################################################
72
73my $z = $LIB->_new("2");
74is($LIB->_str($LIB->_add($x, $z)), 39485,
75   qq|$LIB->_str($LIB->_add(\$x, \$z)) = 39485|);
76my ($re, $rr) = $LIB->_div($x, $y);
77
78is($LIB->_str($re), 123, qq|$LIB->_str(\$re) = 123|);
79is($LIB->_str($rr), 2,   qq|$LIB->_str(\$rr) = 2|);
80
81# is_zero, _is_one, _one, _zero
82
83is($LIB->_is_zero($x) || 0, 0, qq/$LIB->_is_zero(\$x) || 0 = 0/);
84is($LIB->_is_one($x)  || 0, 0, qq/$LIB->_is_one(\$x)  || 0 = 0/);
85
86is($LIB->_str($LIB->_zero()), "0", qq|$LIB->_str($LIB->_zero()) = "0"|);
87is($LIB->_str($LIB->_one()),  "1", qq|$LIB->_str($LIB->_one())  = "1"|);
88
89# _two() and _ten()
90
91is($LIB->_str($LIB->_two()),    "2",  qq|$LIB->_str($LIB->_two()) = "2"|);
92is($LIB->_str($LIB->_ten()),    "10", qq|$LIB->_str($LIB->_ten()) = "10"|);
93is($LIB->_is_ten($LIB->_two()), 0,    qq|$LIB->_is_ten($LIB->_two()) = 0|);
94is($LIB->_is_two($LIB->_two()), 1,    qq|$LIB->_is_two($LIB->_two()) = 1|);
95is($LIB->_is_ten($LIB->_ten()), 1,    qq|$LIB->_is_ten($LIB->_ten()) = 1|);
96is($LIB->_is_two($LIB->_ten()), 0,    qq|$LIB->_is_two($LIB->_ten()) = 0|);
97
98is($LIB->_is_one($LIB->_one()), 1,    qq|$LIB->_is_one($LIB->_one()) = 1|);
99is($LIB->_is_one($LIB->_two()), 0,    qq|$LIB->_is_one($LIB->_two()) = 0|);
100is($LIB->_is_one($LIB->_ten()), 0,    qq|$LIB->_is_one($LIB->_ten()) = 0|);
101
102is($LIB->_is_one($LIB->_zero()) || 0, 0,
103   qq/$LIB->_is_one($LIB->_zero()) || 0 = 0/);
104
105is($LIB->_is_zero($LIB->_zero()), 1,
106   qq|$LIB->_is_zero($LIB->_zero()) = 1|);
107
108is($LIB->_is_zero($LIB->_one()) || 0, 0,
109   qq/$LIB->_is_zero($LIB->_one()) || 0 = 0/);
110
111# is_odd, is_even
112
113is($LIB->_is_odd($LIB->_one()), 1,
114   qq/$LIB->_is_odd($LIB->_one()) = 1/);
115is($LIB->_is_odd($LIB->_zero()) || 0, 0,
116   qq/$LIB->_is_odd($LIB->_zero()) || 0 = 0/);
117is($LIB->_is_even($LIB->_one()) || 0, 0,
118   qq/$LIB->_is_even($LIB->_one()) || 0 = 0/);
119is($LIB->_is_even($LIB->_zero()), 1,
120   qq/$LIB->_is_even($LIB->_zero()) = 1/);
121
122# _len
123
124for my $method (qw/_alen _len/) {
125    $x = $LIB->_new("1");
126    is($LIB->$method($x), 1, qq|$LIB->$method(\$x) = 1|);
127    $x = $LIB->_new("12");
128    is($LIB->$method($x), 2, qq|$LIB->$method(\$x) = 2|);
129    $x = $LIB->_new("123");
130    is($LIB->$method($x), 3, qq|$LIB->$method(\$x) = 3|);
131    $x = $LIB->_new("1234");
132    is($LIB->$method($x), 4, qq|$LIB->$method(\$x) = 4|);
133    $x = $LIB->_new("12345");
134    is($LIB->$method($x), 5, qq|$LIB->$method(\$x) = 5|);
135    $x = $LIB->_new("123456");
136    is($LIB->$method($x), 6, qq|$LIB->$method(\$x) = 6|);
137    $x = $LIB->_new("1234567");
138    is($LIB->$method($x), 7, qq|$LIB->$method(\$x) = 7|);
139    $x = $LIB->_new("12345678");
140    is($LIB->$method($x), 8, qq|$LIB->$method(\$x) = 8|);
141    $x = $LIB->_new("123456789");
142    is($LIB->$method($x), 9, qq|$LIB->$method(\$x) = 9|);
143
144    $x = $LIB->_new("8");
145    is($LIB->$method($x), 1, qq|$LIB->$method(\$x) = 1|);
146    $x = $LIB->_new("21");
147    is($LIB->$method($x), 2, qq|$LIB->$method(\$x) = 2|);
148    $x = $LIB->_new("321");
149    is($LIB->$method($x), 3, qq|$LIB->$method(\$x) = 3|);
150    $x = $LIB->_new("4321");
151    is($LIB->$method($x), 4, qq|$LIB->$method(\$x) = 4|);
152    $x = $LIB->_new("54321");
153    is($LIB->$method($x), 5, qq|$LIB->$method(\$x) = 5|);
154    $x = $LIB->_new("654321");
155    is($LIB->$method($x), 6, qq|$LIB->$method(\$x) = 6|);
156    $x = $LIB->_new("7654321");
157    is($LIB->$method($x), 7, qq|$LIB->$method(\$x) = 7|);
158    $x = $LIB->_new("87654321");
159    is($LIB->$method($x), 8, qq|$LIB->$method(\$x) = 8|);
160    $x = $LIB->_new("987654321");
161    is($LIB->$method($x), 9, qq|$LIB->$method(\$x) = 9|);
162
163    $x = $LIB->_new("0");
164    is($LIB->$method($x), 1, qq|$LIB->$method(\$x) = 1|);
165    $x = $LIB->_new("20");
166    is($LIB->$method($x), 2, qq|$LIB->$method(\$x) = 2|);
167    $x = $LIB->_new("320");
168    is($LIB->$method($x), 3, qq|$LIB->$method(\$x) = 3|);
169    $x = $LIB->_new("4320");
170    is($LIB->$method($x), 4, qq|$LIB->$method(\$x) = 4|);
171    $x = $LIB->_new("54320");
172    is($LIB->$method($x), 5, qq|$LIB->$method(\$x) = 5|);
173    $x = $LIB->_new("654320");
174    is($LIB->$method($x), 6, qq|$LIB->$method(\$x) = 6|);
175    $x = $LIB->_new("7654320");
176    is($LIB->$method($x), 7, qq|$LIB->$method(\$x) = 7|);
177    $x = $LIB->_new("87654320");
178    is($LIB->$method($x), 8, qq|$LIB->$method(\$x) = 8|);
179    $x = $LIB->_new("987654320");
180    is($LIB->$method($x), 9, qq|$LIB->$method(\$x) = 9|);
181
182    for (my $i = 1; $i < 9; $i++) {
183        my $a = "$i" . '0' x ($i - 1);
184        $x = $LIB->_new($a);
185        is($LIB->_len($x), $i, qq|$LIB->_len(\$x) = $i|);
186    }
187}
188
189# _digit
190
191$x = $LIB->_new("123456789");
192is($LIB->_digit($x, 0),   9, qq|$LIB->_digit(\$x, 0) = 9|);
193is($LIB->_digit($x, 1),   8, qq|$LIB->_digit(\$x, 1) = 8|);
194is($LIB->_digit($x, 2),   7, qq|$LIB->_digit(\$x, 2) = 7|);
195is($LIB->_digit($x, 8),   1, qq|$LIB->_digit(\$x, 8) = 1|);
196is($LIB->_digit($x, 9),   0, qq|$LIB->_digit(\$x, 9) = 0|);
197is($LIB->_digit($x, -1),  1, qq|$LIB->_digit(\$x, -1) = 1|);
198is($LIB->_digit($x, -2),  2, qq|$LIB->_digit(\$x, -2) = 2|);
199is($LIB->_digit($x, -3),  3, qq|$LIB->_digit(\$x, -3) = 3|);
200is($LIB->_digit($x, -9),  9, qq|$LIB->_digit(\$x, -9) = 9|);
201is($LIB->_digit($x, -10), 0, qq|$LIB->_digit(\$x, -10) = 0|);
202
203# _copy
204
205foreach (qw/ 1 12 123 1234 12345 123456 1234567 12345678 123456789/) {
206    $x = $LIB->_new("$_");
207    is($LIB->_str($LIB->_copy($x)), "$_",
208       qq|$LIB->_str($LIB->_copy(\$x)) = "$_"|);
209    is($LIB->_str($x), "$_",           # did _copy destroy original x?
210       qq|$LIB->_str(\$x) = "$_"|);
211}
212
213# _zeros
214
215$x = $LIB->_new("1256000000");
216is($LIB->_zeros($x), 6, qq|$LIB->_zeros(\$x) = 6|);
217
218$x = $LIB->_new("152");
219is($LIB->_zeros($x), 0, qq|$LIB->_zeros(\$x) = 0|);
220
221$x = $LIB->_new("123000");
222is($LIB->_zeros($x), 3, qq|$LIB->_zeros(\$x) = 3|);
223
224$x = $LIB->_new("0");
225is($LIB->_zeros($x), 0, qq|$LIB->_zeros(\$x) = 0|);
226
227# _lsft, _rsft
228
229$x = $LIB->_new("10");
230$y = $LIB->_new("3");
231is($LIB->_str($LIB->_lsft($x, $y, 10)), 10000,
232   qq|$LIB->_str($LIB->_lsft(\$x, \$y, 10)) = 10000|);
233
234$x = $LIB->_new("20");
235$y = $LIB->_new("3");
236is($LIB->_str($LIB->_lsft($x, $y, 10)), 20000,
237   qq|$LIB->_str($LIB->_lsft(\$x, \$y, 10)) = 20000|);
238
239$x = $LIB->_new("128");
240$y = $LIB->_new("4");
241is($LIB->_str($LIB->_lsft($x, $y, 2)), 128 << 4,
242   qq|$LIB->_str($LIB->_lsft(\$x, \$y, 2)) = 128 << 4|);
243
244$x = $LIB->_new("1000");
245$y = $LIB->_new("3");
246is($LIB->_str($LIB->_rsft($x, $y, 10)), 1,
247   qq|$LIB->_str($LIB->_rsft(\$x, \$y, 10)) = 1|);
248
249$x = $LIB->_new("20000");
250$y = $LIB->_new("3");
251is($LIB->_str($LIB->_rsft($x, $y, 10)), 20,
252   qq|$LIB->_str($LIB->_rsft(\$x, \$y, 10)) = 20|);
253
254$x = $LIB->_new("256");
255$y = $LIB->_new("4");
256is($LIB->_str($LIB->_rsft($x, $y, 2)), 256 >> 4,
257   qq|$LIB->_str($LIB->_rsft(\$x, \$y, 2)) = 256 >> 4|);
258
259$x = $LIB->_new("6411906467305339182857313397200584952398");
260$y = $LIB->_new("45");
261is($LIB->_str($LIB->_rsft($x, $y, 10)), 0,
262   qq|$LIB->_str($LIB->_rsft(\$x, \$y, 10)) = 0|);
263
264# _acmp
265
266$x = $LIB->_new("123456789");
267$y = $LIB->_new("987654321");
268is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp(\$x, \$y) = -1|);
269is($LIB->_acmp($y, $x), 1,  qq|$LIB->_acmp(\$y, \$x) = 1|);
270is($LIB->_acmp($x, $x), 0,  qq|$LIB->_acmp(\$x, \$x) = 0|);
271is($LIB->_acmp($y, $y), 0,  qq|$LIB->_acmp(\$y, \$y) = 0|);
272$x = $LIB->_new("12");
273$y = $LIB->_new("12");
274is($LIB->_acmp($x, $y), 0,  qq|$LIB->_acmp(\$x, \$y) = 0|);
275$x = $LIB->_new("21");
276is($LIB->_acmp($x, $y), 1,  qq|$LIB->_acmp(\$x, \$y) = 1|);
277is($LIB->_acmp($y, $x), -1, qq|$LIB->_acmp(\$y, \$x) = -1|);
278$x = $LIB->_new("123456789");
279$y = $LIB->_new("1987654321");
280is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp(\$x, \$y) = -1|);
281is($LIB->_acmp($y, $x), +1, qq|$LIB->_acmp(\$y, \$x) = +1|);
282
283$x = $LIB->_new("1234567890123456789");
284$y = $LIB->_new("987654321012345678");
285is($LIB->_acmp($x, $y), 1,  qq|$LIB->_acmp(\$x, \$y) = 1|);
286is($LIB->_acmp($y, $x), -1, qq|$LIB->_acmp(\$y, \$x) = -1|);
287is($LIB->_acmp($x, $x), 0,  qq|$LIB->_acmp(\$x, \$x) = 0|);
288is($LIB->_acmp($y, $y), 0,  qq|$LIB->_acmp(\$y, \$y) = 0|);
289
290$x = $LIB->_new("1234");
291$y = $LIB->_new("987654321012345678");
292is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp(\$x, \$y) = -1|);
293is($LIB->_acmp($y, $x), 1,  qq|$LIB->_acmp(\$y, \$x) = 1|);
294is($LIB->_acmp($x, $x), 0,  qq|$LIB->_acmp(\$x, \$x) = 0|);
295is($LIB->_acmp($y, $y), 0,  qq|$LIB->_acmp(\$y, \$y) = 0|);
296
297# _modinv
298
299$x = $LIB->_new("8");
300$y = $LIB->_new("5033");
301my ($xmod, $sign) = $LIB->_modinv($x, $y);
302is($LIB->_str($xmod), "629",            # -629 % 5033 == 4404
303   qq|$LIB->_str(\$xmod) = "629"|);
304is($sign, "-", q|$sign = "-"|);
305
306# _div
307
308$x = $LIB->_new("3333");
309$y = $LIB->_new("1111");
310is($LIB->_str(scalar($LIB->_div($x, $y))), 3,
311   qq|$LIB->_str(scalar($LIB->_div(\$x, \$y))) = 3|);
312
313$x = $LIB->_new("33333");
314$y = $LIB->_new("1111");
315($x, $y) = $LIB->_div($x, $y);
316is($LIB->_str($x), 30, qq|$LIB->_str(\$x) = 30|);
317is($LIB->_str($y),  3, qq|$LIB->_str(\$y) = 3|);
318
319$x = $LIB->_new("123");
320$y = $LIB->_new("1111");
321($x, $y) = $LIB->_div($x, $y);
322is($LIB->_str($x), 0,   qq|$LIB->_str(\$x) = 0|);
323is($LIB->_str($y), 123, qq|$LIB->_str(\$y) = 123|);
324
325# _num
326
327foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/) {
328
329    $x = $LIB->_new("$_");
330    is(ref($x), "Math::BigInt::Calc",
331       q|ref($x) = "Math::BigInt::Calc"|);
332    is($LIB->_str($x), "$_", qq|$LIB->_str(\$x) = "$_"|);
333
334    $x = $LIB->_num($x);
335    is(ref($x), "", q|ref($x) = ""|);
336    is($x,      $_, qq|\$x = $_|);
337}
338
339# _sqrt
340
341$x = $LIB->_new("144");
342is($LIB->_str($LIB->_sqrt($x)), "12",
343   qq|$LIB->_str($LIB->_sqrt(\$x)) = "12"|);
344$x = $LIB->_new("144000000000000");
345is($LIB->_str($LIB->_sqrt($x)), "12000000",
346   qq|$LIB->_str($LIB->_sqrt(\$x)) = "12000000"|);
347
348# _root
349
350$x = $LIB->_new("81");
351my $n = $LIB->_new("3");        # 4*4*4 = 64, 5*5*5 = 125
352is($LIB->_str($LIB->_root($x, $n)), "4",
353   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "4"|); # 4.xx => 4.0
354
355$x = $LIB->_new("81");
356$n = $LIB->_new("4");          # 3*3*3*3 == 81
357is($LIB->_str($LIB->_root($x, $n)), "3",
358   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "3"|);
359
360# _pow (and _root)
361
362$x = $LIB->_new("0");
363$n = $LIB->_new("3");          # 0 ** y => 0
364is($LIB->_str($LIB->_pow($x, $n)), 0,
365   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 0|);
366
367$x = $LIB->_new("3");
368$n = $LIB->_new("0");          # x ** 0 => 1
369is($LIB->_str($LIB->_pow($x, $n)), 1,
370   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 1|);
371
372$x = $LIB->_new("1");
373$n = $LIB->_new("3");          # 1 ** y => 1
374is($LIB->_str($LIB->_pow($x, $n)), 1,
375   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 1|);
376
377$x = $LIB->_new("5");
378$n = $LIB->_new("1");          # x ** 1 => x
379is($LIB->_str($LIB->_pow($x, $n)), 5,
380   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 5|);
381
382$x = $LIB->_new("81");
383$n = $LIB->_new("3");          # 81 ** 3 == 531441
384is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3,
385   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 81 ** 3|);
386
387is($LIB->_str($LIB->_root($x, $n)), 81,
388   qq|$LIB->_str($LIB->_root(\$x, \$n)) = 81|);
389
390$x = $LIB->_new("81");
391is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3,
392   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 81 ** 3|);
393is($LIB->_str($LIB->_pow($x, $n)), "150094635296999121",      # 531441 ** 3
394   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = "150094635296999121"|);
395
396is($LIB->_str($LIB->_root($x, $n)), "531441",
397   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "531441"|);
398is($LIB->_str($LIB->_root($x, $n)), "81",
399   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "81"|);
400
401$x = $LIB->_new("81");
402$n = $LIB->_new("14");
403is($LIB->_str($LIB->_pow($x, $n)), "523347633027360537213511521",
404   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = "523347633027360537213511521"|);
405is($LIB->_str($LIB->_root($x, $n)), "81",
406   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "81"|);
407
408$x = $LIB->_new("523347633027360537213511520");
409is($LIB->_str($LIB->_root($x, $n)), "80",
410   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "80"|);
411
412$x = $LIB->_new("523347633027360537213511522");
413is($LIB->_str($LIB->_root($x, $n)), "81",
414   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "81"|);
415
416my $res = [ qw/9 31 99 316 999 3162 9999 31622 99999/ ];
417
418# 99 ** 2 = 9801, 999 ** 2 = 998001 etc
419
420for my $i (2 .. 9) {
421    $x = '9' x $i;
422    $x = $LIB->_new($x);
423    $n = $LIB->_new("2");
424    my $rc = '9' x ($i-1). '8' . '0' x ($i - 1) . '1';
425    print "# _pow( ", '9' x $i, ", 2) \n" unless
426      is($LIB->_str($LIB->_pow($x, $n)), $rc,
427         qq|$LIB->_str($LIB->_pow(\$x, \$n)) = $rc|);
428
429  SKIP: {
430        # If $i > $BASE_LEN, the test takes a really long time.
431        skip "$i > $BASE_LEN", 2 unless $i <= $BASE_LEN;
432
433        $x = '9' x $i;
434        $x = $LIB->_new($x);
435        $n = '9' x $i;
436        $n = $LIB->_new($n);
437        print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n";
438        print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n"
439          unless is($LIB->_str($LIB->_root($x, $n)), '1',
440                    qq|$LIB->_str($LIB->_root(\$x, \$n)) = '1'|);
441
442        $x = '9' x $i;
443        $x = $LIB->_new($x);
444        $n = $LIB->_new("2");
445        print "# BASE_LEN $BASE_LEN _root( ", '9' x $i, ", ", 9 x $i, ") \n"
446          unless is($LIB->_str($LIB->_root($x, $n)), $res->[$i-2],
447                    qq|$LIB->_str($LIB->_root(\$x, \$n)) = $res->[$i-2]|);
448    }
449}
450
451##############################################################################
452# _fac
453
454$x = $LIB->_new("0");
455is($LIB->_str($LIB->_fac($x)), "1",
456   qq|$LIB->_str($LIB->_fac(\$x)) = "1"|);
457
458$x = $LIB->_new("1");
459is($LIB->_str($LIB->_fac($x)), "1",
460   qq|$LIB->_str($LIB->_fac(\$x)) = "1"|);
461
462$x = $LIB->_new("2");
463is($LIB->_str($LIB->_fac($x)), "2",
464   qq|$LIB->_str($LIB->_fac(\$x)) = "2"|);
465
466$x = $LIB->_new("3");
467is($LIB->_str($LIB->_fac($x)), "6",
468   qq|$LIB->_str($LIB->_fac(\$x)) = "6"|);
469
470$x = $LIB->_new("4");
471is($LIB->_str($LIB->_fac($x)), "24",
472   qq|$LIB->_str($LIB->_fac(\$x)) = "24"|);
473
474$x = $LIB->_new("5");
475is($LIB->_str($LIB->_fac($x)), "120",
476   qq|$LIB->_str($LIB->_fac(\$x)) = "120"|);
477
478$x = $LIB->_new("10");
479is($LIB->_str($LIB->_fac($x)), "3628800",
480   qq|$LIB->_str($LIB->_fac(\$x)) = "3628800"|);
481
482$x = $LIB->_new("11");
483is($LIB->_str($LIB->_fac($x)), "39916800",
484   qq|$LIB->_str($LIB->_fac(\$x)) = "39916800"|);
485
486$x = $LIB->_new("12");
487is($LIB->_str($LIB->_fac($x)), "479001600",
488   qq|$LIB->_str($LIB->_fac(\$x)) = "479001600"|);
489
490$x = $LIB->_new("13");
491is($LIB->_str($LIB->_fac($x)), "6227020800",
492   qq|$LIB->_str($LIB->_fac(\$x)) = "6227020800"|);
493
494# test that _fac modifies $x in place for small arguments
495
496$x = $LIB->_new("3");
497$LIB->_fac($x);
498is($LIB->_str($x), "6",
499   qq|$LIB->_str(\$x) = "6"|);
500
501$x = $LIB->_new("13");
502$LIB->_fac($x);
503is($LIB->_str($x), "6227020800",
504   qq|$LIB->_str(\$x) = "6227020800"|);
505
506##############################################################################
507# _inc and _dec
508
509for (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/) {
510    $x = $LIB->_new("$_");
511    $LIB->_inc($x);
512    my $expected = substr($_, 0, length($_) - 1) . '2';
513    is($LIB->_str($x), $expected, qq|$LIB->_str(\$x) = $expected|);
514    $LIB->_dec($x);
515    is($LIB->_str($x), $_, qq|$LIB->_str(\$x) = $_|);
516}
517
518for (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/) {
519    $x = $LIB->_new("$_");
520    $LIB->_inc($x);
521    my $expected = substr($_, 0, length($_)-2) . '20';
522    is($LIB->_str($x), $expected, qq|$LIB->_str(\$x) = $expected|);
523    $LIB->_dec($x);
524    is($LIB->_str($x), $_, qq|$LIB->_str(\$x) = $_|);
525}
526
527for (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/) {
528    $x = $LIB->_new("$_");
529    $LIB->_inc($x);
530    my $expected = '1' . '0' x (length($_));
531    is($LIB->_str($x), $expected, qq|$LIB->_str(\$x) = $expected|);
532    $LIB->_dec($x);
533    is($LIB->_str($x), $_, qq|$LIB->_str(\$x) = $_|);
534}
535
536$x = $LIB->_new("1000");
537$LIB->_inc($x);
538is($LIB->_str($x), "1001", qq|$LIB->_str(\$x) = "1001"|);
539$LIB->_dec($x);
540is($LIB->_str($x), "1000", qq|$LIB->_str(\$x) = "1000"|);
541
542my $BL;
543{
544    no strict 'refs';
545    $BL = &{"$LIB"."::_base_len"}();
546}
547
548$x = '1' . '0' x $BL;
549$z = '1' . '0' x ($BL - 1);
550$z .= '1';
551$x = $LIB->_new($x);
552$LIB->_inc($x);
553is($LIB->_str($x), $z, qq|$LIB->_str(\$x) = $z|);
554
555$x = '1' . '0' x $BL;
556$z = '9' x $BL;
557$x = $LIB->_new($x);
558$LIB->_dec($x);
559is($LIB->_str($x), $z, qq|$LIB->_str(\$x) = $z|);
560
561# should not happen:
562# $x = $LIB->_new("-2");
563# $y = $LIB->_new("4");
564# is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp($x, $y) = -1|);
565
566###############################################################################
567# _mod
568
569$x = $LIB->_new("1000");
570$y = $LIB->_new("3");
571is($LIB->_str(scalar($LIB->_mod($x, $y))), 1,
572   qq|$LIB->_str(scalar($LIB->_mod(\$x, \$y))) = 1|);
573
574$x = $LIB->_new("1000");
575$y = $LIB->_new("2");
576is($LIB->_str(scalar($LIB->_mod($x, $y))), 0,
577   qq|$LIB->_str(scalar($LIB->_mod(\$x, \$y))) = 0|);
578
579# _and, _or, _xor
580
581$x = $LIB->_new("5");
582$y = $LIB->_new("2");
583is($LIB->_str(scalar($LIB->_xor($x, $y))), 7,
584   qq|$LIB->_str(scalar($LIB->_xor(\$x, \$y))) = 7|);
585
586$x = $LIB->_new("5");
587$y = $LIB->_new("2");
588is($LIB->_str(scalar($LIB->_or($x, $y))), 7,
589   qq|$LIB->_str(scalar($LIB->_or(\$x, \$y))) = 7|);
590
591$x = $LIB->_new("5");
592$y = $LIB->_new("3");
593is($LIB->_str(scalar($LIB->_and($x, $y))), 1,
594   qq|$LIB->_str(scalar($LIB->_and(\$x, \$y))) = 1|);
595
596# _from_hex, _from_bin, _from_oct
597
598is($LIB->_str($LIB->_from_hex("0xFf")), 255,
599   qq|$LIB->_str($LIB->_from_hex("0xFf")) = 255|);
600is($LIB->_str($LIB->_from_bin("0b10101011")), 160+11,
601   qq|$LIB->_str($LIB->_from_bin("0b10101011")) = 160+11|);
602is($LIB->_str($LIB->_from_oct("0100")), 8*8,
603   qq|$LIB->_str($LIB->_from_oct("0100")) = 8*8|);
604is($LIB->_str($LIB->_from_oct("01000")), 8*8*8,
605   qq|$LIB->_str($LIB->_from_oct("01000")) = 8*8*8|);
606is($LIB->_str($LIB->_from_oct("010001")), 8*8*8*8+1,
607   qq|$LIB->_str($LIB->_from_oct("010001")) = 8*8*8*8+1|);
608is($LIB->_str($LIB->_from_oct("010007")), 8*8*8*8+7,
609   qq|$LIB->_str($LIB->_from_oct("010007")) = 8*8*8*8+7|);
610
611# _as_hex, _as_bin, as_oct
612
613is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("128")))), 128,
614   qq|$LIB->_str($LIB->_from_hex($LIB->_as_hex(|
615   . qq|$LIB->_new("128")))) = 128|);
616is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("128")))), 128,
617   qq|$LIB->_str($LIB->_from_bin($LIB->_as_bin(|
618   . qq|$LIB->_new("128")))) = 128|);
619is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("128")))), 128,
620   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
621   . qq|$LIB->_new("128")))) = 128|);
622
623is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("123456")))),
624   123456,
625   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct|
626   . qq|($LIB->_new("123456")))) = 123456|);
627is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("123456789")))),
628   "123456789",
629   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
630   . qq|$LIB->_new("123456789")))) = "123456789"|);
631is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("1234567890123")))),
632   "1234567890123",
633   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
634   . qq|$LIB->_new("1234567890123")))) = "1234567890123"|);
635
636my $long = "123456789012345678901234567890";
637is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new($long)))), $long,
638   qq|$LIB->_str($LIB->_from_hex($LIB->_as_hex(|
639   . qq|$LIB->_new("$long")))) = "$long"|);
640is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new($long)))), $long,
641   qq|$LIB->_str($LIB->_from_bin($LIB->_as_bin(|
642   . qq|$LIB->_new("$long")))) = "$long"|);
643is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new($long)))), $long,
644   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
645   . qq|$LIB->_new("$long")))) = "$long"|);
646
647is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("0")))), 0,
648   qq|$LIB->_str($LIB->_from_hex($LIB->_as_hex(|
649   . qq|$LIB->_new("0")))) = 0|);
650is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("0")))), 0,
651   qq|$LIB->_str($LIB->_from_bin($LIB->_as_bin(|
652   . qq|$LIB->_new("0")))) = 0|);
653is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("0")))), 0,
654   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
655   . qq|$LIB->_new("0")))) = 0|);
656
657is($LIB->_as_hex($LIB->_new("0")), "0x0",
658   qq|$LIB->_as_hex($LIB->_new("0")) = "0x0"|);
659is($LIB->_as_bin($LIB->_new("0")), "0b0",
660   qq|$LIB->_as_bin($LIB->_new("0")) = "0b0"|);
661is($LIB->_as_oct($LIB->_new("0")), "00",
662   qq|$LIB->_as_oct($LIB->_new("0")) = "00"|);
663
664is($LIB->_as_hex($LIB->_new("12")), "0xc",
665   qq|$LIB->_as_hex($LIB->_new("12")) = "0xc"|);
666is($LIB->_as_bin($LIB->_new("12")), "0b1100",
667   qq|$LIB->_as_bin($LIB->_new("12")) = "0b1100"|);
668is($LIB->_as_oct($LIB->_new("64")), "0100",
669   qq|$LIB->_as_oct($LIB->_new("64")) = "0100"|);
670
671# _1ex
672
673is($LIB->_str($LIB->_1ex(0)), "1",
674   qq|$LIB->_str($LIB->_1ex(0)) = "1"|);
675is($LIB->_str($LIB->_1ex(1)), "10",
676   qq|$LIB->_str($LIB->_1ex(1)) = "10"|);
677is($LIB->_str($LIB->_1ex(2)), "100",
678   qq|$LIB->_str($LIB->_1ex(2)) = "100"|);
679is($LIB->_str($LIB->_1ex(12)), "1000000000000",
680   qq|$LIB->_str($LIB->_1ex(12)) = "1000000000000"|);
681is($LIB->_str($LIB->_1ex(16)), "10000000000000000",
682   qq|$LIB->_str($LIB->_1ex(16)) = "10000000000000000"|);
683
684# _check
685
686$x = $LIB->_new("123456789");
687is($LIB->_check($x), 0,
688   qq|$LIB->_check(\$x) = 0|);
689is($LIB->_check(123), "123 is not a reference",
690   qq|$LIB->_check(123) = "123 is not a reference"|);
691
692###############################################################################
693# __strip_zeros
694
695{
696    no strict 'refs';
697
698    # correct empty arrays
699    $x = &{$LIB."::__strip_zeros"}([]);
700    is(@$x, 1, q|@$x = 1|);
701    is($x->[0], 0, q|$x->[0] = 0|);
702
703    # don't strip single elements
704    $x = &{$LIB."::__strip_zeros"}([0]);
705    is(@$x, 1, q|@$x = 1|);
706    is($x->[0], 0, q|$x->[0] = 0|);
707    $x = &{$LIB."::__strip_zeros"}([1]);
708    is(@$x, 1, q|@$x = 1|);
709    is($x->[0], 1, q|$x->[0] = 1|);
710
711    # don't strip non-zero elements
712    $x = &{$LIB."::__strip_zeros"}([0, 1]);
713    is(@$x, 2, q|@$x = 2|);
714    is($x->[0], 0, q|$x->[0] = 0|);
715    is($x->[1], 1, q|$x->[1] = 1|);
716    $x = &{$LIB."::__strip_zeros"}([0, 1, 2]);
717    is(@$x, 3, q|@$x = 3|);
718    is($x->[0], 0, q|$x->[0] = 0|);
719    is($x->[1], 1, q|$x->[1] = 1|);
720    is($x->[2], 2, q|$x->[2] = 2|);
721
722    # but strip leading zeros
723    $x = &{$LIB."::__strip_zeros"}([0, 1, 2, 0]);
724    is(@$x, 3, q|@$x = 3|);
725    is($x->[0], 0, q|$x->[0] = 0|);
726    is($x->[1], 1, q|$x->[1] = 1|);
727    is($x->[2], 2, q|$x->[2] = 2|);
728
729    $x = &{$LIB."::__strip_zeros"}([0, 1, 2, 0, 0]);
730    is(@$x, 3, q|@$x = 3|);
731    is($x->[0], 0, q|$x->[0] = 0|);
732    is($x->[1], 1, q|$x->[1] = 1|);
733    is($x->[2], 2, q|$x->[2] = 2|);
734
735    $x = &{$LIB."::__strip_zeros"}([0, 1, 2, 0, 0, 0]);
736    is(@$x, 3, q|@$x = 3|);
737    is($x->[0], 0, q|$x->[0] = 0|);
738    is($x->[1], 1, q|$x->[1] = 1|);
739    is($x->[2], 2, q|$x->[2] = 2|);
740
741    # collapse multiple zeros
742    $x = &{$LIB."::__strip_zeros"}([0, 0, 0, 0]);
743    is(@$x, 1, q|@$x = 1|);
744    is($x->[0], 0, q|$x->[0] = 0|);
745}
746
747# done
748
7491;
750