1#!perl
2
3use strict;
4use warnings;
5
6use Test::More tests => 460;
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# _lsft() with large bases
265
266for my $xstr ("1", "2", "3") {
267    for my $nstr ("1", "2", "3") {
268        for my $bpow (25, 50, 75) {
269            my $bstr = "1" . ("0" x $bpow);
270            my $expected = $xstr . ("0" x ($bpow * $nstr));
271            my $xobj = $LIB->_new($xstr);
272            my $nobj = $LIB->_new($nstr);
273            my $bobj = $LIB->_new($bstr);
274
275            is($LIB->_str($LIB->_lsft($xobj, $nobj, $bobj)), $expected,
276               qq|$LIB->_str($LIB->_lsft($LIB->_new("$xstr"), |
277                                    . qq|$LIB->_new("$nstr"), |
278                                    . qq|$LIB->_new("$bstr")))|);
279            is($LIB->_str($nobj), $nstr, q|$n is unmodified|);
280            is($LIB->_str($bobj), $bstr, q|$b is unmodified|);
281        }
282    }
283}
284
285# _acmp
286
287$x = $LIB->_new("123456789");
288$y = $LIB->_new("987654321");
289is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp(\$x, \$y) = -1|);
290is($LIB->_acmp($y, $x), 1,  qq|$LIB->_acmp(\$y, \$x) = 1|);
291is($LIB->_acmp($x, $x), 0,  qq|$LIB->_acmp(\$x, \$x) = 0|);
292is($LIB->_acmp($y, $y), 0,  qq|$LIB->_acmp(\$y, \$y) = 0|);
293$x = $LIB->_new("12");
294$y = $LIB->_new("12");
295is($LIB->_acmp($x, $y), 0,  qq|$LIB->_acmp(\$x, \$y) = 0|);
296$x = $LIB->_new("21");
297is($LIB->_acmp($x, $y), 1,  qq|$LIB->_acmp(\$x, \$y) = 1|);
298is($LIB->_acmp($y, $x), -1, qq|$LIB->_acmp(\$y, \$x) = -1|);
299$x = $LIB->_new("123456789");
300$y = $LIB->_new("1987654321");
301is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp(\$x, \$y) = -1|);
302is($LIB->_acmp($y, $x), +1, qq|$LIB->_acmp(\$y, \$x) = +1|);
303
304$x = $LIB->_new("1234567890123456789");
305$y = $LIB->_new("987654321012345678");
306is($LIB->_acmp($x, $y), 1,  qq|$LIB->_acmp(\$x, \$y) = 1|);
307is($LIB->_acmp($y, $x), -1, qq|$LIB->_acmp(\$y, \$x) = -1|);
308is($LIB->_acmp($x, $x), 0,  qq|$LIB->_acmp(\$x, \$x) = 0|);
309is($LIB->_acmp($y, $y), 0,  qq|$LIB->_acmp(\$y, \$y) = 0|);
310
311$x = $LIB->_new("1234");
312$y = $LIB->_new("987654321012345678");
313is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp(\$x, \$y) = -1|);
314is($LIB->_acmp($y, $x), 1,  qq|$LIB->_acmp(\$y, \$x) = 1|);
315is($LIB->_acmp($x, $x), 0,  qq|$LIB->_acmp(\$x, \$x) = 0|);
316is($LIB->_acmp($y, $y), 0,  qq|$LIB->_acmp(\$y, \$y) = 0|);
317
318# _modinv
319
320$x = $LIB->_new("8");
321$y = $LIB->_new("5033");
322my ($xmod, $sign) = $LIB->_modinv($x, $y);
323is($LIB->_str($xmod), "629",            # -629 % 5033 == 4404
324   qq|$LIB->_str(\$xmod) = "629"|);
325is($sign, "-", q|$sign = "-"|);
326
327# _div
328
329$x = $LIB->_new("3333");
330$y = $LIB->_new("1111");
331is($LIB->_str(scalar($LIB->_div($x, $y))), 3,
332   qq|$LIB->_str(scalar($LIB->_div(\$x, \$y))) = 3|);
333
334$x = $LIB->_new("33333");
335$y = $LIB->_new("1111");
336($x, $y) = $LIB->_div($x, $y);
337is($LIB->_str($x), 30, qq|$LIB->_str(\$x) = 30|);
338is($LIB->_str($y),  3, qq|$LIB->_str(\$y) = 3|);
339
340$x = $LIB->_new("123");
341$y = $LIB->_new("1111");
342($x, $y) = $LIB->_div($x, $y);
343is($LIB->_str($x), 0,   qq|$LIB->_str(\$x) = 0|);
344is($LIB->_str($y), 123, qq|$LIB->_str(\$y) = 123|);
345
346# _num
347
348foreach (qw/1 12 123 1234 12345 1234567 12345678 123456789 1234567890/) {
349
350    $x = $LIB->_new("$_");
351    is(ref($x), "Math::BigInt::Calc",
352       q|ref($x) = "Math::BigInt::Calc"|);
353    is($LIB->_str($x), "$_", qq|$LIB->_str(\$x) = "$_"|);
354
355    $x = $LIB->_num($x);
356    is(ref($x), "", q|ref($x) = ""|);
357    is($x,      $_, qq|\$x = $_|);
358}
359
360# _sqrt
361
362$x = $LIB->_new("144");
363is($LIB->_str($LIB->_sqrt($x)), "12",
364   qq|$LIB->_str($LIB->_sqrt(\$x)) = "12"|);
365$x = $LIB->_new("144000000000000");
366is($LIB->_str($LIB->_sqrt($x)), "12000000",
367   qq|$LIB->_str($LIB->_sqrt(\$x)) = "12000000"|);
368
369# _root
370
371$x = $LIB->_new("81");
372my $n = $LIB->_new("3");        # 4*4*4 = 64, 5*5*5 = 125
373is($LIB->_str($LIB->_root($x, $n)), "4",
374   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "4"|); # 4.xx => 4.0
375
376$x = $LIB->_new("81");
377$n = $LIB->_new("4");          # 3*3*3*3 == 81
378is($LIB->_str($LIB->_root($x, $n)), "3",
379   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "3"|);
380
381# _pow (and _root)
382
383$x = $LIB->_new("0");
384$n = $LIB->_new("3");          # 0 ** y => 0
385is($LIB->_str($LIB->_pow($x, $n)), 0,
386   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 0|);
387
388$x = $LIB->_new("3");
389$n = $LIB->_new("0");          # x ** 0 => 1
390is($LIB->_str($LIB->_pow($x, $n)), 1,
391   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 1|);
392
393$x = $LIB->_new("1");
394$n = $LIB->_new("3");          # 1 ** y => 1
395is($LIB->_str($LIB->_pow($x, $n)), 1,
396   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 1|);
397
398$x = $LIB->_new("5");
399$n = $LIB->_new("1");          # x ** 1 => x
400is($LIB->_str($LIB->_pow($x, $n)), 5,
401   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 5|);
402
403$x = $LIB->_new("81");
404$n = $LIB->_new("3");          # 81 ** 3 == 531441
405is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3,
406   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 81 ** 3|);
407
408is($LIB->_str($LIB->_root($x, $n)), 81,
409   qq|$LIB->_str($LIB->_root(\$x, \$n)) = 81|);
410
411$x = $LIB->_new("81");
412is($LIB->_str($LIB->_pow($x, $n)), 81 ** 3,
413   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = 81 ** 3|);
414is($LIB->_str($LIB->_pow($x, $n)), "150094635296999121",      # 531441 ** 3
415   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = "150094635296999121"|);
416
417is($LIB->_str($LIB->_root($x, $n)), "531441",
418   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "531441"|);
419is($LIB->_str($LIB->_root($x, $n)), "81",
420   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "81"|);
421
422$x = $LIB->_new("81");
423$n = $LIB->_new("14");
424is($LIB->_str($LIB->_pow($x, $n)), "523347633027360537213511521",
425   qq|$LIB->_str($LIB->_pow(\$x, \$n)) = "523347633027360537213511521"|);
426is($LIB->_str($LIB->_root($x, $n)), "81",
427   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "81"|);
428
429$x = $LIB->_new("523347633027360537213511520");
430is($LIB->_str($LIB->_root($x, $n)), "80",
431   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "80"|);
432
433$x = $LIB->_new("523347633027360537213511522");
434is($LIB->_str($LIB->_root($x, $n)), "81",
435   qq|$LIB->_str($LIB->_root(\$x, \$n)) = "81"|);
436
437my $res = [ qw/9 31 99 316 999 3162 9999 31622 99999/ ];
438
439# 99 ** 2 = 9801, 999 ** 2 = 998001 etc
440
441for my $i (2 .. 9) {
442    $x = '9' x $i;
443    $x = $LIB->_new($x);
444    $n = $LIB->_new("2");
445    my $rc = '9' x ($i-1). '8' . '0' x ($i - 1) . '1';
446    print "# _pow( ", '9' x $i, ", 2) \n" unless
447      is($LIB->_str($LIB->_pow($x, $n)), $rc,
448         qq|$LIB->_str($LIB->_pow(\$x, \$n)) = $rc|);
449
450  SKIP: {
451        # If $i > $BASE_LEN, the test takes a really long time.
452        skip "$i > $BASE_LEN", 2 unless $i <= $BASE_LEN;
453
454        $x = '9' x $i;
455        $x = $LIB->_new($x);
456        $n = '9' x $i;
457        $n = $LIB->_new($n);
458        print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n";
459        print "# _root( ", '9' x $i, ", ", 9 x $i, ") \n"
460          unless is($LIB->_str($LIB->_root($x, $n)), '1',
461                    qq|$LIB->_str($LIB->_root(\$x, \$n)) = '1'|);
462
463        $x = '9' x $i;
464        $x = $LIB->_new($x);
465        $n = $LIB->_new("2");
466        print "# BASE_LEN $BASE_LEN _root( ", '9' x $i, ", ", 9 x $i, ") \n"
467          unless is($LIB->_str($LIB->_root($x, $n)), $res->[$i-2],
468                    qq|$LIB->_str($LIB->_root(\$x, \$n)) = $res->[$i-2]|);
469    }
470}
471
472##############################################################################
473# _fac
474
475$x = $LIB->_new("0");
476is($LIB->_str($LIB->_fac($x)), "1",
477   qq|$LIB->_str($LIB->_fac(\$x)) = "1"|);
478
479$x = $LIB->_new("1");
480is($LIB->_str($LIB->_fac($x)), "1",
481   qq|$LIB->_str($LIB->_fac(\$x)) = "1"|);
482
483$x = $LIB->_new("2");
484is($LIB->_str($LIB->_fac($x)), "2",
485   qq|$LIB->_str($LIB->_fac(\$x)) = "2"|);
486
487$x = $LIB->_new("3");
488is($LIB->_str($LIB->_fac($x)), "6",
489   qq|$LIB->_str($LIB->_fac(\$x)) = "6"|);
490
491$x = $LIB->_new("4");
492is($LIB->_str($LIB->_fac($x)), "24",
493   qq|$LIB->_str($LIB->_fac(\$x)) = "24"|);
494
495$x = $LIB->_new("5");
496is($LIB->_str($LIB->_fac($x)), "120",
497   qq|$LIB->_str($LIB->_fac(\$x)) = "120"|);
498
499$x = $LIB->_new("10");
500is($LIB->_str($LIB->_fac($x)), "3628800",
501   qq|$LIB->_str($LIB->_fac(\$x)) = "3628800"|);
502
503$x = $LIB->_new("11");
504is($LIB->_str($LIB->_fac($x)), "39916800",
505   qq|$LIB->_str($LIB->_fac(\$x)) = "39916800"|);
506
507$x = $LIB->_new("12");
508is($LIB->_str($LIB->_fac($x)), "479001600",
509   qq|$LIB->_str($LIB->_fac(\$x)) = "479001600"|);
510
511$x = $LIB->_new("13");
512is($LIB->_str($LIB->_fac($x)), "6227020800",
513   qq|$LIB->_str($LIB->_fac(\$x)) = "6227020800"|);
514
515# test that _fac modifies $x in place for small arguments
516
517$x = $LIB->_new("3");
518$LIB->_fac($x);
519is($LIB->_str($x), "6",
520   qq|$LIB->_str(\$x) = "6"|);
521
522$x = $LIB->_new("13");
523$LIB->_fac($x);
524is($LIB->_str($x), "6227020800",
525   qq|$LIB->_str(\$x) = "6227020800"|);
526
527##############################################################################
528# _inc and _dec
529
530for (qw/1 11 121 1231 12341 1234561 12345671 123456781 1234567891/) {
531    $x = $LIB->_new("$_");
532    $LIB->_inc($x);
533    my $expected = substr($_, 0, length($_) - 1) . '2';
534    is($LIB->_str($x), $expected, qq|$LIB->_str(\$x) = $expected|);
535    $LIB->_dec($x);
536    is($LIB->_str($x), $_, qq|$LIB->_str(\$x) = $_|);
537}
538
539for (qw/19 119 1219 12319 1234519 12345619 123456719 1234567819/) {
540    $x = $LIB->_new("$_");
541    $LIB->_inc($x);
542    my $expected = substr($_, 0, length($_)-2) . '20';
543    is($LIB->_str($x), $expected, qq|$LIB->_str(\$x) = $expected|);
544    $LIB->_dec($x);
545    is($LIB->_str($x), $_, qq|$LIB->_str(\$x) = $_|);
546}
547
548for (qw/999 9999 99999 9999999 99999999 999999999 9999999999 99999999999/) {
549    $x = $LIB->_new("$_");
550    $LIB->_inc($x);
551    my $expected = '1' . '0' x (length($_));
552    is($LIB->_str($x), $expected, qq|$LIB->_str(\$x) = $expected|);
553    $LIB->_dec($x);
554    is($LIB->_str($x), $_, qq|$LIB->_str(\$x) = $_|);
555}
556
557$x = $LIB->_new("1000");
558$LIB->_inc($x);
559is($LIB->_str($x), "1001", qq|$LIB->_str(\$x) = "1001"|);
560$LIB->_dec($x);
561is($LIB->_str($x), "1000", qq|$LIB->_str(\$x) = "1000"|);
562
563my $BL;
564{
565    no strict 'refs';
566    $BL = &{"$LIB"."::_base_len"}();
567}
568
569$x = '1' . '0' x $BL;
570$z = '1' . '0' x ($BL - 1);
571$z .= '1';
572$x = $LIB->_new($x);
573$LIB->_inc($x);
574is($LIB->_str($x), $z, qq|$LIB->_str(\$x) = $z|);
575
576$x = '1' . '0' x $BL;
577$z = '9' x $BL;
578$x = $LIB->_new($x);
579$LIB->_dec($x);
580is($LIB->_str($x), $z, qq|$LIB->_str(\$x) = $z|);
581
582# should not happen:
583# $x = $LIB->_new("-2");
584# $y = $LIB->_new("4");
585# is($LIB->_acmp($x, $y), -1, qq|$LIB->_acmp($x, $y) = -1|);
586
587###############################################################################
588# _mod
589
590$x = $LIB->_new("1000");
591$y = $LIB->_new("3");
592is($LIB->_str(scalar($LIB->_mod($x, $y))), 1,
593   qq|$LIB->_str(scalar($LIB->_mod(\$x, \$y))) = 1|);
594
595$x = $LIB->_new("1000");
596$y = $LIB->_new("2");
597is($LIB->_str(scalar($LIB->_mod($x, $y))), 0,
598   qq|$LIB->_str(scalar($LIB->_mod(\$x, \$y))) = 0|);
599
600# _and, _or, _xor
601
602$x = $LIB->_new("5");
603$y = $LIB->_new("2");
604is($LIB->_str(scalar($LIB->_xor($x, $y))), 7,
605   qq|$LIB->_str(scalar($LIB->_xor(\$x, \$y))) = 7|);
606
607$x = $LIB->_new("5");
608$y = $LIB->_new("2");
609is($LIB->_str(scalar($LIB->_or($x, $y))), 7,
610   qq|$LIB->_str(scalar($LIB->_or(\$x, \$y))) = 7|);
611
612$x = $LIB->_new("5");
613$y = $LIB->_new("3");
614is($LIB->_str(scalar($LIB->_and($x, $y))), 1,
615   qq|$LIB->_str(scalar($LIB->_and(\$x, \$y))) = 1|);
616
617# _from_hex, _from_bin, _from_oct
618
619is($LIB->_str($LIB->_from_hex("0xFf")), 255,
620   qq|$LIB->_str($LIB->_from_hex("0xFf")) = 255|);
621is($LIB->_str($LIB->_from_bin("0b10101011")), 160+11,
622   qq|$LIB->_str($LIB->_from_bin("0b10101011")) = 160+11|);
623is($LIB->_str($LIB->_from_oct("0100")), 8*8,
624   qq|$LIB->_str($LIB->_from_oct("0100")) = 8*8|);
625is($LIB->_str($LIB->_from_oct("01000")), 8*8*8,
626   qq|$LIB->_str($LIB->_from_oct("01000")) = 8*8*8|);
627is($LIB->_str($LIB->_from_oct("010001")), 8*8*8*8+1,
628   qq|$LIB->_str($LIB->_from_oct("010001")) = 8*8*8*8+1|);
629is($LIB->_str($LIB->_from_oct("010007")), 8*8*8*8+7,
630   qq|$LIB->_str($LIB->_from_oct("010007")) = 8*8*8*8+7|);
631
632# _as_hex, _as_bin, as_oct
633
634is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("128")))), 128,
635   qq|$LIB->_str($LIB->_from_hex($LIB->_as_hex(|
636   . qq|$LIB->_new("128")))) = 128|);
637is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("128")))), 128,
638   qq|$LIB->_str($LIB->_from_bin($LIB->_as_bin(|
639   . qq|$LIB->_new("128")))) = 128|);
640is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("128")))), 128,
641   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
642   . qq|$LIB->_new("128")))) = 128|);
643
644is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("123456")))),
645   123456,
646   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct|
647   . qq|($LIB->_new("123456")))) = 123456|);
648is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("123456789")))),
649   "123456789",
650   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
651   . qq|$LIB->_new("123456789")))) = "123456789"|);
652is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("1234567890123")))),
653   "1234567890123",
654   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
655   . qq|$LIB->_new("1234567890123")))) = "1234567890123"|);
656
657my $long = "123456789012345678901234567890";
658is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new($long)))), $long,
659   qq|$LIB->_str($LIB->_from_hex($LIB->_as_hex(|
660   . qq|$LIB->_new("$long")))) = "$long"|);
661is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new($long)))), $long,
662   qq|$LIB->_str($LIB->_from_bin($LIB->_as_bin(|
663   . qq|$LIB->_new("$long")))) = "$long"|);
664is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new($long)))), $long,
665   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
666   . qq|$LIB->_new("$long")))) = "$long"|);
667
668is($LIB->_str($LIB->_from_hex($LIB->_as_hex($LIB->_new("0")))), 0,
669   qq|$LIB->_str($LIB->_from_hex($LIB->_as_hex(|
670   . qq|$LIB->_new("0")))) = 0|);
671is($LIB->_str($LIB->_from_bin($LIB->_as_bin($LIB->_new("0")))), 0,
672   qq|$LIB->_str($LIB->_from_bin($LIB->_as_bin(|
673   . qq|$LIB->_new("0")))) = 0|);
674is($LIB->_str($LIB->_from_oct($LIB->_as_oct($LIB->_new("0")))), 0,
675   qq|$LIB->_str($LIB->_from_oct($LIB->_as_oct(|
676   . qq|$LIB->_new("0")))) = 0|);
677
678is($LIB->_as_hex($LIB->_new("0")), "0x0",
679   qq|$LIB->_as_hex($LIB->_new("0")) = "0x0"|);
680is($LIB->_as_bin($LIB->_new("0")), "0b0",
681   qq|$LIB->_as_bin($LIB->_new("0")) = "0b0"|);
682is($LIB->_as_oct($LIB->_new("0")), "00",
683   qq|$LIB->_as_oct($LIB->_new("0")) = "00"|);
684
685is($LIB->_as_hex($LIB->_new("12")), "0xc",
686   qq|$LIB->_as_hex($LIB->_new("12")) = "0xc"|);
687is($LIB->_as_bin($LIB->_new("12")), "0b1100",
688   qq|$LIB->_as_bin($LIB->_new("12")) = "0b1100"|);
689is($LIB->_as_oct($LIB->_new("64")), "0100",
690   qq|$LIB->_as_oct($LIB->_new("64")) = "0100"|);
691
692# _1ex
693
694is($LIB->_str($LIB->_1ex(0)), "1",
695   qq|$LIB->_str($LIB->_1ex(0)) = "1"|);
696is($LIB->_str($LIB->_1ex(1)), "10",
697   qq|$LIB->_str($LIB->_1ex(1)) = "10"|);
698is($LIB->_str($LIB->_1ex(2)), "100",
699   qq|$LIB->_str($LIB->_1ex(2)) = "100"|);
700is($LIB->_str($LIB->_1ex(12)), "1000000000000",
701   qq|$LIB->_str($LIB->_1ex(12)) = "1000000000000"|);
702is($LIB->_str($LIB->_1ex(16)), "10000000000000000",
703   qq|$LIB->_str($LIB->_1ex(16)) = "10000000000000000"|);
704
705# _check
706
707$x = $LIB->_new("123456789");
708is($LIB->_check($x), 0,
709   qq|$LIB->_check(\$x) = 0|);
710is($LIB->_check(123), "123 is not a reference",
711   qq|$LIB->_check(123) = "123 is not a reference"|);
712
713###############################################################################
714# __strip_zeros
715
716{
717    no strict 'refs';
718
719    # correct empty arrays
720    $x = &{$LIB."::__strip_zeros"}([]);
721    is(@$x, 1, q|@$x = 1|);
722    is($x->[0], 0, q|$x->[0] = 0|);
723
724    # don't strip single elements
725    $x = &{$LIB."::__strip_zeros"}([0]);
726    is(@$x, 1, q|@$x = 1|);
727    is($x->[0], 0, q|$x->[0] = 0|);
728    $x = &{$LIB."::__strip_zeros"}([1]);
729    is(@$x, 1, q|@$x = 1|);
730    is($x->[0], 1, q|$x->[0] = 1|);
731
732    # don't strip non-zero elements
733    $x = &{$LIB."::__strip_zeros"}([0, 1]);
734    is(@$x, 2, q|@$x = 2|);
735    is($x->[0], 0, q|$x->[0] = 0|);
736    is($x->[1], 1, q|$x->[1] = 1|);
737    $x = &{$LIB."::__strip_zeros"}([0, 1, 2]);
738    is(@$x, 3, q|@$x = 3|);
739    is($x->[0], 0, q|$x->[0] = 0|);
740    is($x->[1], 1, q|$x->[1] = 1|);
741    is($x->[2], 2, q|$x->[2] = 2|);
742
743    # but strip leading zeros
744    $x = &{$LIB."::__strip_zeros"}([0, 1, 2, 0]);
745    is(@$x, 3, q|@$x = 3|);
746    is($x->[0], 0, q|$x->[0] = 0|);
747    is($x->[1], 1, q|$x->[1] = 1|);
748    is($x->[2], 2, q|$x->[2] = 2|);
749
750    $x = &{$LIB."::__strip_zeros"}([0, 1, 2, 0, 0]);
751    is(@$x, 3, q|@$x = 3|);
752    is($x->[0], 0, q|$x->[0] = 0|);
753    is($x->[1], 1, q|$x->[1] = 1|);
754    is($x->[2], 2, q|$x->[2] = 2|);
755
756    $x = &{$LIB."::__strip_zeros"}([0, 1, 2, 0, 0, 0]);
757    is(@$x, 3, q|@$x = 3|);
758    is($x->[0], 0, q|$x->[0] = 0|);
759    is($x->[1], 1, q|$x->[1] = 1|);
760    is($x->[2], 2, q|$x->[2] = 2|);
761
762    # collapse multiple zeros
763    $x = &{$LIB."::__strip_zeros"}([0, 0, 0, 0]);
764    is(@$x, 1, q|@$x = 1|);
765    is($x->[0], 0, q|$x->[0] = 0|);
766}
767
768# done
769
7701;
771